<?php

namespace AppBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use AppBundle\Controller\HuobiKLine1minController;
use AppBundle\Controller\HuobiKLine5minController;
use AppBundle\Controller\HuobiKLine30minController;

class MQCommand extends ContainerAwareCommand
{
    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this
            ->setName('app:task:async')
            ->setDescription('async exec api.');
    }

    private function alertModelServices($kline = null)
    {
        if ($kline == HuobiKLine1minController::CACHE_KLINE_KEY) {
            $services = [
                'app.task.alert_model6.1',
                'app.task.alert_model6.2',
                'app.task.alert_model6.3',
                'app.task.alert_model6.4',
                'app.task.alert_model6.3.5',
                'app.task.alert_model6.4.5',

//                'app.task.alert_model1.0',
//                'app.task.alert_model1.1',
//                'app.task.alert_model2.0',
////            'app.task.alert_model2.1',
////            'app.task.alert_model2.2',
//                'app.task.alert_model2.3',
//                'app.task.alert_model2.4',
//                'app.task.alert_model2.5',
////            'app.task.alert_model2.6',
////            'app.task.alert_model2.7',
//                'app.task.alert_model2.8',
//                'app.task.alert_model3.0',
//                'app.task.alert_model3.1',
//                'app.task.alert_model3.2',
////            'app.task.alert_model3.3',
////            'app.task.alert_model3.4',
////            'app.task.alert_model3.5',
//                'app.task.alert_model6.0',
            ];
        } elseif ($kline == HuobiKLine5minController::CACHE_KLINE_KEY) {
            $services = [
                'app.task.alert_model7.1',
                'app.task.alert_model7.2',
                'app.task.alert_model7.3',
                'app.task.alert_model7.4',
                'app.task.alert_model7.5',
                'app.task.alert_model7.6',
                'app.task.alert_model7.7',
                'app.task.alert_model7.8',
            ];
//        } elseif ($kline == HuobiKLine30minController::CACHE_KLINE_KEY) {
//            $services = [
//                'app.task.alert_model8.1',
//                'app.task.alert_model8.2',
//                'app.task.alert_model8.3',
//                'app.task.alert_model8.4',
//                'app.task.alert_model9.1',
//                'app.task.alert_model9.3',
//            ];

        } else {
            $services = [];
        }
        return $services;
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln($this->convert(memory_get_usage(true)));

        $redis = $this->getContainer()->get('huobi.redis');
        $blocking_keys = array(
            HuobiKLine1minController::CACHE_KLINE_KEY,
            HuobiKLine5minController::CACHE_KLINE_KEY,
            HuobiKLine30minController::CACHE_KLINE_KEY,
        );
        while (1) {
            $output->writeln('sleeping about 10s at ' . date('Y-m-d H:i:s'));

            $content = $redis->brPop($blocking_keys, 10);

            if (empty($content)) {
                continue;
            }

            $kline = $content[0];
            $data = json_decode($content[1], true);

            $channel = explode('.', $data['ch']);
            $coin = $channel[1];
//            $kline = end($channel);

            $tick = $data['tick'];
            $tick['coin'] = $coin;
            $tick['time_stamp'] = $tick['id'];
            $output->writeln($kline);

            foreach ($this->alertModelServices($kline) as $task) {

                $job = $this->getContainer()->get($task);

                $output->writeln(sprintf("%s --> %s , %s", $task, $coin, date('Y-m-d H:i:s')));

                $api_json = $job->run($tick);

                $output->writeln(date('Y-m-d H:i:s'));

                if ($api_json == null)
                    continue;

                $output->writeln($job->version());

                $redis->lPush($job->getCacheKey(), $api_json);

                $output->writeln($api_json);
            }

            if ($this->checkMemory($output) > 0) {
                $output->writeln('memory limit.');
                return;
            }
        }
    }

    private function convert($size)
    {
        $unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
        return @round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $unit[$i];
    }

    private function checkMemory($output = null)
    {
        $max_memory = pow(1024, 2) * 100;
        $usage_memory = memory_get_usage();

        if ($usage_memory > $max_memory) {

            $dir_root = dirname($this->getContainer()->getParameter('kernel.root_dir'));
            $command = 'cd ' . $dir_root . ' && php bin/console app:task:async > /dev/null 2>&1 &';

            // 异步启用后台处理进程
            if ($resource = popen($command, 'r')) {
                pclose($resource);
            }
            sleep(5);
            return $max_memory;
        }
        if ($output) {
            $output->writeln('----*----');
            $output->writeln($this->convert($usage_memory));
        }
        return 0;
    }
}
